<?php
// 检查物流规则缺失数据
namespace app\admin\jobs;

use app\admin\model\LogisticsRules;
use app\common\service\CompleteNotificationService;
use think\facade\Log;
use Exception;
use Throwable;

class CheckMissingLogisticsRule
{
    private $logisticsRulesModel;

    public function __construct()
    {
        $this->logisticsRulesModel = new LogisticsRules();
    }

    public function execute()
    {
        try {
            Log::info('CheckMissingLogisticsRule: 开始执行物流规则缺失检查');

            // 获取基础数据
            $baseData = $this->getBaseData();

            if (empty($baseData)) {
                Log::warning('CheckMissingLogisticsRule: 基础数据为空，跳过检查');
                return;
            }

            [
                'warehouse_list' => $warehouse_list,
                'country_list' => $country_list,
                'all_rule_list' => $all_rule_list,
                'cc_names_list' => $cc_names_list
            ] = $baseData;

            // 构建规则索引以提升查找效率
            $rule_index = $this->buildRuleIndex($all_rule_list);

            $no_rule_list = [];
            $processed_count = 0;

            foreach ($cc_names_list as $cc_name) {
                try {
                    $missing_rules = $this->processCcName($cc_name, $warehouse_list, $country_list, $rule_index);
                    $no_rule_list = array_merge($no_rule_list, $missing_rules);
                    $processed_count++;
                } catch (Exception $e) {
                    Log::error('CheckMissingLogisticsRule: 处理cc_name失败', [
                        'cc_name_id' => $cc_name['id'] ?? 'unknown',
                        'error' => $e->getMessage()
                    ]);
                    continue; // 跳过当前cc_name，继续处理下一个
                }
            }

            Log::info('CheckMissingLogisticsRule: 处理完成', [
                'processed_cc_names' => $processed_count,
                'total_cc_names' => count($cc_names_list),
                'missing_rules_count' => count($no_rule_list)
            ]);

            // 发送通知
            if (!empty($no_rule_list)) {
                $this->sendNotification($no_rule_list, $warehouse_list, $country_list);
            } else {
                Log::info('CheckMissingLogisticsRule: 没有发现缺失的物流规则');
            }
        } catch (Throwable $e) {
            Log::error('CheckMissingLogisticsRule: 执行失败', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);
            throw $e; // 重新抛出异常，让上层处理
        }
    }

    /**
     * 获取基础数据
     */
    private function getBaseData(): array
    {
        try {
            $warehouse_list = $this->logisticsRulesModel
                ->name('warehouse')
                ->where('is_del', 0)
                ->where('status', 1)
                ->field('id,name,fl_warehouse_id')
                ->select()
                ->toArray();

            if (empty($warehouse_list)) {
                Log::warning('CheckMissingLogisticsRule: 仓库列表为空');
                return [];
            }
            $warehouse_list = array_column($warehouse_list, null, 'id');

            $country_list = $this->logisticsRulesModel
                ->name('region_country')
                ->field('id,cname,ccname_id')
                ->select()
                ->toArray();

            if (empty($country_list)) {
                Log::warning('CheckMissingLogisticsRule: 国家列表为空');
                return [];
            }
            $country_list = array_column($country_list, null, 'id');

            $all_rule_list = $this->logisticsRulesModel
                ->field('to_nation,shipping_warehouse,terms,prescription')
                ->group('to_nation,shipping_warehouse,terms,prescription')
                ->where('is_del', 0)
                ->where('status', 1)
                ->where('prescription', 1)
                ->where('execution_date', '<', date('Y-m-d H:i:s'))
                ->select()
                ->toArray();

            $cc_names_list = $this->logisticsRulesModel
                ->name('cc_names')
                ->where('is_del', 0)
                ->field('id,sellable_wids')
                ->select()
                ->toArray();

            if (empty($cc_names_list)) {
                Log::warning('CheckMissingLogisticsRule: cc_names列表为空');
                return [];
            }

            return compact('warehouse_list', 'country_list', 'all_rule_list', 'cc_names_list');
        } catch (Exception $e) {
            Log::error('CheckMissingLogisticsRule: 获取基础数据失败', ['error' => $e->getMessage()]);
            throw $e;
        }
    }

    /**
     * 构建规则索引以提升查找效率
     */
    private function buildRuleIndex(array $all_rule_list): array
    {
        $rule_index = [];
        foreach ($all_rule_list as $rule) {
            $key = sprintf(
                '%s_%s_%s_%s',
                $rule['to_nation'],
                $rule['shipping_warehouse'],
                $rule['terms'],
                $rule['prescription']
            );
            $rule_index[$key] = true;
        }

        Log::info('CheckMissingLogisticsRule: 规则索引构建完成', [
            'total_rules' => count($all_rule_list),
            'unique_combinations' => count($rule_index)
        ]);

        return $rule_index;
    }

    /**
     * 处理单个cc_name
     */
    private function processCcName(array $cc_name, array $warehouse_list, array $country_list, array $rule_index): array
    {
        if (empty($cc_name['sellable_wids'])) {
            return [];
        }

        // 获取当前仓库列表
        $sellable_wids = array_filter(explode(',', $cc_name['sellable_wids']));
        $current_warehouse_ids = [];

        foreach ($warehouse_list as $warehouse) {
            if (in_array($warehouse['fl_warehouse_id'], $sellable_wids)) {
                $current_warehouse_ids[] = $warehouse['id'];
            }
        }

        if (empty($current_warehouse_ids)) {
            return [];
        }

        // 获取当前国家列表
        $current_country_ids = [];
        foreach ($country_list as $country) {
            if ($country['ccname_id'] == $cc_name['id']) {
                $current_country_ids[] = $country['id'];
            }
        }
        $current_country_ids = array_unique($current_country_ids);

        if (empty($current_country_ids)) {
            return [];
        }

        // 检查缺失规则
        $missing_rules = [];
        foreach ($current_country_ids as $country_id) {
            foreach ($current_warehouse_ids as $warehouse_id) {
                // 检查两种运输方式
                for ($terms = 1; $terms <= 2; $terms++) {
                    $key = sprintf('%s_%s_%s_%s', $country_id, $warehouse_id, $terms, 1);
                    if (!isset($rule_index[$key])) {
                        $missing_rules[] = [$country_id, $warehouse_id, $terms, 1];
                    }
                }
            }
        }

        return $missing_rules;
    }

    /**
     * 发送通知
     */
    private function sendNotification(array $no_rule_list, array $warehouse_list, array $country_list): void
    {
        try {
            if (empty($no_rule_list)) {
                return;
            }

            $no_rule_list_str = '您有' . count($no_rule_list) . '条物流规则缺失，请及时处理：' . "\n\n";

            foreach ($no_rule_list as $key => $no_rule) {
                if (!isset($country_list[$no_rule[0]]) || !isset($warehouse_list[$no_rule[1]])) {
                    Log::warning('CheckMissingLogisticsRule: 缺失规则数据不完整', [
                        'country_id' => $no_rule[0],
                        'warehouse_id' => $no_rule[1]
                    ]);
                    continue;
                }

                if ($key > 99) {
                    $no_rule_list_str .= '......';
                    break;
                }

                $country = $country_list[$no_rule[0]]['cname'];
                $warehouse = $warehouse_list[$no_rule[1]]['name'];
                $terms = $no_rule[2] == 1 ? 'DDP' : 'DDU';
                $prescription = $no_rule[3] == 1 ? '普快' : '特快';
                $no_rule_list_str .= sprintf(
                    '发货仓库:%s,目的国家:%s,报关方式:%s,时效:%s;%s',
                    $warehouse,
                    $country,
                    $terms,
                    $prescription,
                    "\n\n"
                );
            }

            $completeNotificationService = new CompleteNotificationService();
            $res = $completeNotificationService->send('missing_logistics_rule', [], [], $no_rule_list_str);

            if ($res['code'] == 0) {
                Log::info('CheckMissingLogisticsRule: 通知发送成功', [
                    'missing_rules_count' => count($no_rule_list)
                ]);
            } else {
                Log::error('CheckMissingLogisticsRule: 通知发送失败', [
                    'error' => $res['message'],
                    'missing_rules_count' => count($no_rule_list)
                ]);
            }
        } catch (Exception $e) {
            Log::error('CheckMissingLogisticsRule: 发送通知失败', [
                'error' => $e->getMessage(),
                'missing_rules_count' => count($no_rule_list)
            ]);
            throw $e;
        }
    }
}
